#include <webx/menu.h>
#include <webx/route.h>
#include <http/HttpHelper.h>

class ExecModule : public webx::ProcessBase
{
protected:
	int process();
};

HTTP_WEBCGI(CGI_PROTECT, "${filename}")
DEFINE_HTTP_CGI_EXPORT_FUNC(ExecModule)

static HttpServer* app = HttpServer::Instance();

static bool SystemCommand(char cmd)
{
	return stdx::async([cmd](){
		static char* data = app->getShareData()->data;

		data[0] = cmd;
		data[1] = '-';

		Socket().connect(app->getHost(), app->getPort());
	});
}

EXTERN_DLL_FUNC int HttpPluginInit(IHttpServer* app)
{
	return XG_OK;
}

int ExecModule::process()
{
	param_string(cmd);
    param_string(type);
	param_string(name);

	webx::CheckSystemRight(this);

	int res = 0;
	string root = app->getPath();

	stdx::tolower(cmd);
	stdx::tolower(type);

	if (cmd == "get")
	{
		out << webx::GetRemoteConfig(type, name);

		return XG_OK;
	}
	else if (cmd == "sync")
	{
		res = webx::SyncRemoteConfig(type, name);
	}
	else if (cmd == "call")
	{
		param_int(async);
		param_string(path);
		param_string(param);

		webx::CheckFilePath(path);

		if (async > 0)
		{
			res = stdx::async([=](){
				webx::GetRemoteResult(path, param);
			}) ? XG_OK : XG_SYSBUSY;
		}
		else
		{
			SmartBuffer data = webx::GetRemoteResult(path, param);

			if (data.isNull()) return simpleResponse(XG_SYSERR);

			clearResponse();

			out << data.str();

			return data.size();
		}
	}
	else if (cmd == "updatemodule")
	{
		param_string(src);
		param_string(dest);

		if (src.length() < 7) return simpleResponse(XG_PARAMERR);

		if (memcmp(src.c_str(), "http://", 7) == 0)
		{
			XFile file;
			SmartBuffer data = HttpHelper::GetResult(src);

			if (data.size() < 0xFF) return simpleResponse(XG_ERROR);

			src = "/dat/" + path::name(dest);

			file.open(root + src, eCREATE);

			if (file.write(data.str(), data.size()) < 0) return simpleResponse(XG_ERROR);
		}

		src = root + src;
		src = stdx::replace(src, "\\", "/");
		src = stdx::replace(src, "//", "/");

		if (path::type(src) == eFILE)
		{
			param_int(port);
			param_string(host);
			param_string(flag);

			if (host.length() > 0)
			{
				string path;
				HttpRequest request(getClassName());

				if (flag == "R")
				{
					src = src.substr(root.length());
				}
				else
				{
					char* addrlist[32];

					if (GetLocalAddress(addrlist) <= 0) return simpleResponse(XG_ERROR);

					path = root + "dat/pub/" + path::name(src);

					path::rename(src, path);

					src = path.substr(root.length());
					src = HttpHelper::GetLink(src, addrlist[0], app->getPort());
				}

				request.setParameter("cmd", cmd);
				request.setParameter("src", src);
				request.setParameter("dest", dest);

				SmartBuffer data = request.getResult(host, port);

				if (path.length() > 0) path::remove(path);

				if (data.isNull()) return simpleResponse(XG_ERROR);

				out << data.str();

				return XG_OK;
			}

			dest = root + dest;
			dest = stdx::replace(dest, "\\", "/");
			dest = stdx::replace(dest, "//", "/");

			stdx::async([=](){
				app->updateModuleFile(src, dest);
			});

			Sleep(100);
		}
	}
	else
	{
		param_int(port);
		param_string(host);

		if (host.length() > 0)
		{
			HttpRequest request(getClassName());

			request.setParameter("cmd", cmd);

			SmartBuffer data = request.getResult(host, port);

			if (data.isNull()) return simpleResponse(XG_ERROR);

			out << data.str();

			return XG_OK;
		}

		if (cmd == "exit")
		{
			res = SystemCommand('k') ? XG_OK : XG_ERROR;
		}
		else if (cmd == "reload")
		{
			res = SystemCommand('r') ? XG_OK : XG_ERROR;
		}
		else if (cmd == "restart")
		{
			res = SystemCommand('s') ? XG_OK : XG_ERROR;
		}
		else
		{
			stdx::Throw(XG_PARAMERR, "invalid parameter[cmd]");
		}
	}

	json["datetime"] = DateTime::ToString();
	json["code"] = res;
	out << json;

	return XG_OK;
}